import asyncio
import time

from webutils.webargs.bare import use_args

from .. import handwriting, params, services


class HandwritingMixin:
    async def on_binary_message(self, conn, message):
        frame = handwriting.TransportFrame.from_bytes(message)
        if frame.action == 1:
            await self.save_handwriting(frame, conn)

    async def save_handwriting(self, frame, conn):
        service = services.Handwriting(
            conn,
            room_id=self.session.room_id,
            user_id=frame.user_id,
        )
        await service.write(frame)

    async def background_send_handwriting(self):
        previous_position_dct = position_dct = {}
        while True:
            user_id_lst = self.session.get('handwriting_followee', [])
            async with self.get_connection() as conn:
                for user_id in user_id_lst:
                    position_dct.setdefault(user_id, (time.time(), 0))
                    service = services.Handwriting(
                        conn,
                        room_id=self.session.room_id,
                        user_id=user_id,
                    )
                    refresh_time, position = position_dct[user_id]
                    refresh_time, position = await service.sync_position(
                        refresh_time, position)
                    record = await service.read(size=200)
                    if record:
                        await self.write_message(record, binary=True)
                    position_dct[user_id] = (refresh_time, service.tell())
            if previous_position_dct == position_dct:
                await asyncio.sleep(0.5)
            previous_position_dct = position_dct

    @use_args({
        'get': params.Receiver(required=True),
    })
    async def on_act_subscribe_handwriting(self, args, conn):
        if self.session.get('handwriting_followee') is None:
            self.session.handwriting_followee = set()
        for user_id in args['get']['users']:
            self.session.handwriting_followee.add(user_id)
        if self.session.handwriting_followee:
            self.start_background_task('send_handwriting')

    @use_args({
        'get': params.Receiver(required=True),
    })
    async def on_act_unsubscribe_handwriting(self, args, conn):
        if self.session.get('handwriting_followee') is None:
            self.session.handwriting_followee = set()
        for user_id in args['get']['users']:
            self.session.handwriting_followee.discard(user_id)
        if not self.session.handwriting_followee:
            self.stop_background_task('send_handwriting')
